import * as XLSX from "xlsx";
import Taro from "@tarojs/taro";

export interface ExcelColumn<T>{
    key:string
    header:string
    renderToString?:(item:T)=>string
}

export function exportToWorkbook<T>(data:T[],columns:ExcelColumn<T>[]){
    const sheet:any[][] = []
    const excelHeader = columns.map(it=>it.header)
    sheet.push(excelHeader)

    data.map(item => {
        const object = {};

        function isValidValue(value: any) {
            return typeof value == "string" || typeof value == "number" || typeof value == "undefined";
        }
        let row:any[] = [];
        for (let i = 0; i < columns.length; i++) {
            let column = columns[i];
            let key = (column.key as unknown as string);
            let value = item[key];

            if (column.renderToString) {
                row.push(column.renderToString(item))
            } else {
                if (!!value) {
                    if (isValidValue(value)) {
                        row.push(value);
                    }else {
                        throw new Error(`unknown value:${value} key:${key}`);
                    }
                }else {
                    row.push(undefined);
                }
            }

        }
        sheet.push(row)
        return object
    })
    var ws = XLSX.utils.aoa_to_sheet(sheet);
    var wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Sheet 1");
    adjustColumnWidth(columns,sheet,ws)
    return  wb


}

function adjustColumnWidth<T>(columns:ExcelColumn<T>[],sheetData:any[][],worksheet: XLSX.WorkSheet) {
    let wscols = columns.map((_, index)=>{
        let lengthList = sheetData.map(row=>row[index]).map(value=>{
            let string = value?.toString();
            if (string) {
                let match = string.match(/[\u4e00-\u9fa5]/);
                return string.length + (match?.join("")?.length ?? 0) + 2
            }else {
                return 0
            }
        });
        return Math.max(...lengthList)
    }).map(width=>({width}));

    worksheet["!cols"] = wscols;
}

export function saveAndOpenWorkbook(workbook:XLSX.WorkBook,name:string){
    let fileData = XLSX.write(workbook, {
        bookType: "xlsx",
        type: 'base64'
    });
    const fs = Taro.getFileSystemManager()
    let filePath = `${Taro.env.USER_DATA_PATH}/${name}.xlsx`;
    return new Promise((resolve, reject) => {
        fs.writeFile({
            filePath,
            data: fileData,
            encoding: "base64",
            success: async () => {
                await Taro.openDocument({
                    showMenu: true,
                    filePath: filePath,
                    fileType: "xlsx",
                })
                resolve(undefined)
            },
            fail: reject,
        })
    })
}